<?php
/**
 * Created by Administrator
 * User: longli
 * VX: isa1589518286
 * Date: 2020/08/12
 * Time: 10:47
 * @link http://www.lmterp.cn
 */

namespace app\common\service\platform;

use app\common\library\Tools;
use app\common\model\AccountSyncLog;
use app\common\model\Orders;
use app\common\model\OrdersTemp;
use app\common\service\orders\OrderService;
use think\facade\Log;

/**
 * allegro 接口服务
 * Class AllegroService
 * @package app\common\service\allegro
 * @link https://developer.allegro.pl/en/documentation/
 */
class AllegroService extends BasePlatformService
{
    public static $tokenField = [
        'required' => [ // 必填字段
            [
                'type' => 'text',
                'name' => 'client_id',
                'field' => 'client_id',
            ],
            [
                'type' => 'text',
                'name' => 'client_secret',
                'field' => 'client_secret',
            ],
            [
                'type' => 'text',
                'name' => 'refresh_token',
                'field' => 'refresh_token',
            ],
        ],
        'option' => [ // 可选字段
            [
                'type' => 'text',
                'name' => 'access_token',
                'field' => 'access_token',
                //'readonly' => true,
            ],
        ],
    ];

    public function init()
    {
        $this->offsetDate = date('Z');
    }

    /**
     * 同步订单列表
     * @param array $params 请求参数
     * @param bool $replace 是否替换原有的订单
     * @date 2020/08/17
     * @author longli
     * @example [
     *  'page_size' => 100,
     *  'status' => 'READY_FOR_PROCESSING',
     *  'start_date' => '2020-08-07',
     *  'end_date' => '2020-08-08',
     * ]
     */
    public function getOrderList($params = [], $replace = false)
    {
        Log::info(sprintf("Allegro 批量同步账号【%d】订单，请求参数: 【%s】", $this->getAccountId(), json_encode($params)));
        $args = [
            'limit' => !empty($params['page_size']) && $params['page_size'] < 101 ? $params = ['page_size'] : 100,
            'status' => !empty($params['status']) ? $params['status'] : 'READY_FOR_PROCESSING',
            'lineItems.boughtAt.gte' => $this->formatTimeToDate(!empty($params['start_date']) ? $params['start_date'] : date('Y-m-d')), // '2020-08-10T00:00:00Z'
            'lineItems.boughtAt.lte' => !empty($params['end_date']) ? $this->formatTimeToDate($params['end_date']) : $this->formatTimeToDate(),
        ];
        $url = $this->getBaseUrl() . "/order/checkout-forms";
        $startSyncTime = time();
        $page = 0;
        $refresh = 0;
        do
        {
            $refreshToken = false;
            $args['offset'] = $page * $args['limit'];
            $response = Tools::curlGet($url, $args, $this->getHeader());
            if(!$response['status'])
            {
                if($response['info']['http_code'] == 401)
                {
                    if($refresh++ > 3) break;
                    $this->refreshToken(); // 刷新 token
                    $refreshToken = true;
                    continue;
                }
                Log::info(sprintf("Allegro 账号【%d】订单，同步订单请求出错，响应信息: 【%s】", $this->getAccountId(), json_encode($response['info'])));
                break;
            }
            if(!Tools::isJson($response['data'], $orderData) || !empty($orderData['error']))
            {
                Log::info(sprintf("Allegro 账号【%d】订单，同步订单出错，响应信息: 【%s】", $this->getAccountId(), json_encode($orderData)));
                break;
            }
            foreach($orderData['checkoutForms'] as $order)
            {
                // 如果订单已存在则直接跳过
               $this->pushOrderToTemp($order['id'], $order, $replace);
            }
            $page++;
        }while($refreshToken || $orderData['count'] == $args['limit']);
        // 添加同步订单日志
        AccountSyncLog::addLog($this->getAccountId(), $startSyncTime, time(), $args);
    }

    /**
     * 同步一条订单数据
     * @param OrdersTemp $orderTemp 一条订单数据
     * @return bool
     * @date 2020/08/19
     * @author longli
     */
    public function syncOrder(OrdersTemp $orderTemp)
    {
        $platform = $this->getAccountById($orderTemp['account_id'])->platform;
        $data = $orderTemp->order_info;
        $info = [];
        foreach($data['lineItems'] as $detail)
        {
            $info[] = [
                "platform_sku"      => $detail['offer']['external']['id'], // 平台 sku
                "name"              => $detail['offer']['name'], // 产品在平台的名称
                "qty"               => $detail['quantity'],
                "price"             => $detail['price']['amount'],
            ];
        }
        $order = [
            "order_no"                  => $data['id'],
            "account_id"                => $orderTemp->account_id,
            "platform_name"             => $platform->name, // 平台名称
            "order_platform_status"     => $data['status'], // 订单在平台的状态
            "buyer_email"               => $data['buyer']['email'],
            "buyer_account"             => $data['buyer']['login'], // 买家登录账号
            "buyer_first_name"          => $data['delivery']['address']["firstName"],
            "buyer_last_name"           => $data['delivery']['address']["lastName"],
            "buyer_company"             => $data['delivery']['address']["companyName"]?:'',
            "buyer_mobile"              => $data['delivery']['address']["phoneNumber"],
            "buyer_country_code"        => $data['delivery']['address']['countryCode'],
            "buyer_district"            => $data['delivery']['address']['street'],
            "buyer_city"                => $data['delivery']['address']['city'],
            "buyer_address_1"           => "{$data['delivery']['address']['city']} {$data['delivery']['address']['street']}",
            "buyer_post_code"           => $data['delivery']['address']['zipCode'],
            "prime_cost"                => $data['delivery']['cost']['amount'], // 订单成本
            "latest_delivery_time"      => $data['delivery']['time']['guaranteed']['to']
                                            ? $this->parseTimeToDate($data['delivery']['time']['guaranteed']['to'], $this->offsetDate)
                                            : null, // 最迟发货时间
            "order_price"               => $data['payment']['paidAmount']['amount'], // 订单金额
            "surcharge_price"           => !empty($data['surcharges']) ? $data['surcharges'][0]['paidAmount']['amount'] : 0, // 订单附加费用
            "total_price"               => $data['summary']['totalToPay']['amount'], // 订单总金额
            "order_pay_time"            => $this->parseTimeToDate($data['payment']['finishedAt'], $this->offsetDate), // 订单支付时间
            "currency"                  => $data['payment']['paidAmount']['currency'], // 币种
            "order_source_create_time"  => $this->parseTimeToDate($data['updatedAt'], $this->offsetDate), // 订单在平台生成时间
            "invoice_title"             => $data['invoice']['address']['company']['name']?:'', // 发票抬头
            "invoice_detail"            => $data['invoice']['address'] ? json_encode($data['invoice']['address']) : '', // 发票内容
            "platform_remark"           => $data['messageToSeller']?:'', // 平台订单备注
            'order_detail'              => $info,
        ];
        return OrderService::getInstance()->addOrder($order);
    }

    /**
     * 刷新 token
     * @date 2020/08/18
     * @author longli
     */
    public function refreshToken()
    {
        Log::info(sprintf("Allegro 账号【%d】刷新 token", $this->getAccountId()));
        $account = $this->getAccount();
        $url = "https://allegro.pl/auth/oauth/token?grant_type=refresh_token&refresh_token={$account->token->refresh_token}&redirect_uri={$account->account_id}";
        $header = [
            "Authorization:Basic " . base64_encode("{$account->token->client_id}:{$account->token->client_secret}"),
        ];
        $response = Tools::curlPost($url, '', $header);
        if(!$response['status'] || !Tools::isJson($response['data'], $data))
        {
            Log::info(sprintf("Allegro 账号【%d】刷新 token 出错，响应信息: 【%s】", $this->getAccountId(), $response['data']));
            return false;
        }
        $account->token->access_token = $data['access_token'];
        $account->token->refresh_token = $data['refresh_token'];
        $account->save();
        return true;
    }

    /**
     * 获取请求信息带加密
     * @date 2020/08/12
     * @author longli
     * @return array
     */
    public function getHeader()
    {
        $account = $this->getAccount();
        return [
            'Content-Type:application/vnd.allegro.public.v1+json',
            'Accept:application/vnd.allegro.public.v1+json',
            'Authorization:Bearer ' . $account->token->access_token
        ];
    }

    public function markDelivery($orderIds = [])
    {
        foreach($this->getNeedMarkOrders($orderIds) as $order)
        {
            $url = $this->getBaseUrl() . "/order/checkout-forms/{$order->order_no}/shipments";
            $skus = [];
            foreach($order->detail as $detail)
            {
                $skus[] = ['id' => $detail->platform_sku];
            }
            $postData = [
                'carrierId' => $order->logistics_name,
                'waybill' => $order->track_num,
                'lineItems' => $skus
            ];
            $response = Tools::curlPost($url, json_encode($postData), $this->getHeader());
            if(!$response['status'] && !Tools::isJson($response['data'], $result))
            {
                Log::info(sprintf("Allegro 订单号【%s】标记失败，错误信息【%s】", $order->order_no, $response['data']));
                continue;
            }
            if(!empty($result['waibill']))
            {
                $order->is_flag_sent = Orders::FLAG_SENT_YES;
                $order->sent_time = Tools::now();
                $order->save();
            }
        }
    }
}